# -*- coding: utf-8 -*-
from crawler.utils.mysql_util import *
from crawler.utils.redis_util import *
from crawler.core import dict_sql
from fontTools.ttLib import TTFont
from lxml import etree
import  base64, re, io

class BaseService(object):
    """
    @author Hongv
    @desc 业务方法基类
    """
    sql_conn = MysqlUtil()
    redis_coon = RedisUtil()

    def get_crawler_urls(self, tag=''):
        # 根据tag获取要爬取的urls
        try:
            tag = self.urls_tag if not tag else tag
            sql = dict_sql.crawlerUrls.format(tag=tag)
            result = [url[0] for url in self.sql_conn.get_all(sql)]
            return result
        except Exception as e:
            raise e

    def get_ip_proxies(self, redis_table, pool_type='list'):
        # 获取代理
        if pool_type=='list':
            result = self.redis_coon.lindex(redis_table, index='random')
        else:
            result = self.redis_coon.srandmember(redis_table, 1)
        return result

    def task_is_running(self, task_id, sec=20):
        # 判断任务是否已经在执行
        task = settings.REDIS_TASK_RUNNING.format(task_id=task_id)
        reply = self.redis_coon.setnx(task, 1)
        if (reply == True):
            self.redis_coon.expire(task, sec)
            return False
        else:
            return True

    def get_link_redis(self, key):
        return self.redis_coon.exists(key)

    def get_code(self, code_type, name, sub_str=None):
        try:
            # code_type: city orientation web
            if not code_type or not name: raise Exception('Params Not Complete')
            redis_table = settings.REDIS_CODES.get(code_type, '')
            if sub_str: redis_table = redis_table.format(sub_str=sub_str)
            result = self.redis_coon.hget(redis_table, name)
            return result.decode().replace('"','')
        except:
            return ''

    def get_time_by_diff(self, base_time):
        # TODO 逻辑有漏洞 待优化
        # 根据页面显示的时间差计算时间 eg: 1分钟前 2天前
        diff_time, diff_unit = 30, ''
        if '刚刚' in base_time:
            diff_unit = 'continue'
            diff_time = '0'
            new_time = base_time
        elif '分钟' in base_time:
            diff_unit = 'minutes'
            diff_time = ibase_time.split('分钟')[0]
            new_time = self.get_next_time(int(diff_time), unit='minutes')
            if diff_time == '1': new_time = ''
        elif '小时' in base_time:
            diff_unit = 'hours'
            diff_time = base_time.split('小时')[0]
            new_time = self.get_next_time(int(diff_time), unit='hours')
        elif '天' in base_time:
            diff_unit = 'days'
            diff_time = base_time.split('天')[0]
            new_time = self.get_next_time(int(diff_time), unit='days')
        else:
            diff_unit = 'continue'
            diff_time = '0'
            new_time = base_time
        return new_time, diff_unit, diff_time

    def check_time_diff(self, localtime, basetime, diff_unit, diff_time):
        # TODO 当服务器时间不准时会有Bug 需优化
        # 判断当前时间与发布时间的时间差 与 页面显示的时间差 是否一致
        diff = False
        local_time_diff = self.get_time_differ(localtime, basetime).seconds
        if diff_unit == 'days':
            local_time_diff = ceil(local_time_diff / (60 * 60 * 24))
        elif diff_unit == 'hours':
            local_time_diff = ceil(local_time_diff / (60 * 60))
        elif diff_unit == 'minutes':
            local_time_diff = ceil(local_time_diff / 60)
        if diff_unit != 'continue' and local_time_diff - int(diff_time) > 1:
            diff = True
        return diff

    def get_next_time(self, diff_time, unit='minutes'):
        if unit == 'days':
            return (datetime.datetime.now() - datetime.timedelta(days=diff_time)).strftime("%Y-%m-%d %H:%M:%S")
        if unit == 'hours':
            return (datetime.datetime.now() - datetime.timedelta(hours=diff_time)).strftime("%Y-%m-%d %H:%M:%S")
        if unit == 'minutes':
            return (datetime.datetime.now() - datetime.timedelta(minutes=diff_time)).strftime("%Y-%m-%d %H:%M:%S")

    def get_time_differ(self, date1, date2):
        # 获取两个时间的时间差
        date1 = datetime.datetime.strptime(date1, "%Y-%m-%d %H:%M:%S")
        date2 = datetime.datetime.strptime(date2, "%Y-%m-%d %H:%M:%S")
        if date1 < date2:
            return date2 - date1
        else:
            return date1 - date2

    def stamp13_to_str(self, timeStamp):
        '''
        13位时间戳转时间
        :param timeStamp:
        :return:
        '''
        timeStamp = float(int(timeStamp) / 1000)
        timeArray = time.localtime(timeStamp)
        otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
        return otherStyleTime

    def replace_font(self, response):
        try:
            base64_str = re.search("base64,(.*?)'\)", response.text).group(1)
            b = base64.b64decode(base64_str)
            font = TTFont(io.BytesIO(b))
            bestcmap = font['cmap'].getBestCmap()
            newmap = dict()
            for key in bestcmap.keys():
                value = int(re.search(r'(\d+)', bestcmap[key]).group(1)) - 1
                key = hex(key)
                newmap[key] = value
            response_ = response.text
            for key, value in newmap.items():
                key_ = key.replace('0x', '&#x') + ';'
                if key_ in response_:
                    response_ = response_.replace(key_, str(value))
            return etree.HTML(response_)
        except Exception as e:
            raise e

    def dispose(self):
        self.sql_conn.dispose()

    def end(self):
        self.sql_conn.end()

class EsfOwnerService(BaseService):
    """
    @author Hongv
    @desc 出售*二手房*个人 业务方法
    """
    def __init__(self, urls_tag='ershoufang_owner'):
        self.urls_tag = urls_tag

    def get_house_redis(self, house_id, web_code):
        # 判断数据是否已存在 (为提高查询效率，部分数据信息在mysql与redis中做了双份保存)
        try:
            redis_table = settings.REDIS_HOUSES_CSOWNER.format(webcode=web_code)
            result = self.redis_coon.hget(redis_table, house_id)
            if not result:
                result = self.get_house_mysql(house_id, web_code)
            else:
                result = ['', '', '', result.decode()]
            return result
        except Exception as e:
            raise e

    def get_house_mysql(self, house_id, web_code):
        try:
            sql = dict_sql.esf_owner_get.format(house_id=house_id, web_code=web_code)
            result = self.sql_conn.get_one(sql)
            return result
        except Exception as e:
            raise e

    def update_house_status(self, house_id, web_code, title, published_time):
        try:
            redis_table = settings.REDIS_HOUSES_CSOWNER.format(webcode=web_code)
            sql = dict_sql.esf_owner_update_status.format(published_time=published_time, title=title, house_id=house_id, web_code=web_code)
            self.redis_coon.hset(redis_table, house_id, published_time)
            result = self.sql_conn.update(sql)
            return result
        except Exception as e:
            raise e

    def update_house(self, item):
        try:
            sets, wheres = [], []
            for k, v in item._values.items():
                if k == 'house_id' or k=='web_belong':
                    wheres.append("%s='%s'" % (k, v))
                elif k == 'builtuparea' or k == 'total_price':
                    sets.append("%s=%d" % (k, int(float(v or 0) * 100)))
                elif v and v != 'None':
                    sets.append("%s='%s'" % (k, v))
                else:
                    sets.append("%s=null" % k)
            sql = dict_sql.esf_owner_update % (','.join(sets), ' and '.join(wheres))
            result = self.sql_conn.update(sql)
            return result
        except Exception as e:
            raise e

    def insert_house(self, item):
        try:
            keys, values = [], []
            for k, v in item._values.items():
                keys.append(k)
                if k=='total_price' or k == 'builtuparea':
                    values.append(str(int(float(v or 0)*100)))
                elif v and isinstance(v,int):
                    values.append(str(v))
                elif v and v != 'None':
                    values.append("'%s'" % v)
                else:
                    values.append('null')
            sql = dict_sql.esf_owner_insert % (','.join(keys), ','.join(values))
            result = self.sql_conn.insert(sql)
            return result
        except Exception as e:
            raise e

    def insert_info_redis(self, info, table=''):
        redis_table = settings.REDIS_DETAILLINK_CSOWNER if not table else table
        self.redis_coon.sadd(redis_table, info)

class RentOwnerService(BaseService):
    """
    @author Hongv
    @desc 出售*二手房*个人 业务方法
    """
    def __init__(self, urls_tag='chuzu_owner'):
        self.urls_tag = urls_tag

    def get_house_redis(self, house_id, web_code):
        # 判断数据是否已存在 (为提高查询效率，部分数据信息在mysql与redis中做了双份保存)
        try:
            redis_table = settings.REDIS_HOUSES_CZOWNER.format(webcode=web_code)
            result = self.redis_coon.hget(redis_table, house_id)
            if not result:
                result = self.get_house_mysql(house_id, web_code)
            else:
                result = ['', '', '', result.decode()]
            return result
        except Exception as e:
            raise e

    def get_house_mysql(self, house_id, web_code):
        try:
            sql = dict_sql.rent_owner_get.format(house_id=house_id, web_code=web_code)
            result = self.sql_conn.get_one(sql)
            return result
        except Exception as e:
            raise e

    def update_house_status(self, house_id, web_code, published_time):
        try:
            redis_table = settings.REDIS_HOUSES_CZOWNER.format(webcode=web_code)
            sql = dict_sql.rent_owner_update_status.format(published_time=published_time, house_id=house_id, web_code=web_code)
            self.redis_coon.hset(redis_table, house_id, published_time)
            result = self.sql_conn.update(sql)
            return result
        except Exception as e:
            raise e

    def update_house(self, item):
        try:
            sets, wheres = [], []
            for k, v in item._values.items():
                if k == 'house_id' or k=='web_belong':
                    wheres.append("%s='%s'" % (k, v))
                elif k == 'total_price' or k == 'builtuparea':
                    sets.append("%s=%d" % (k, int(float(v or 0)*100)))
                elif k == 'unit_price':
                    sets.append("%s=%d" % (k, int(float(v or 0)*100)))
                elif v and v != 'None':
                    sets.append("%s='%s'" % (k, v))
                else:sets.append("%s=null" % k)
            sql = dict_sql.rent_owner_update % (','.join(sets), ' and '.join(wheres))
            result = self.sql_conn.update(sql)
            return result
        except Exception as e:
            raise e

    def insert_house(self, item):
        try:
            keys, values = [], []
            for k, v in item._values.items():
                keys.append(k)
                if k == 'unit_price'  or k == 'builtuparea':
                    values.append(str(int(float(v or 0)*100)))
                elif v and isinstance(v,int):
                    values.append(str(v))
                elif v and v != 'None':
                    values.append("'%s'" % v)
                else:values.append('null')
            sql = dict_sql.rent_owner_insert % (','.join(keys), ','.join(values))
            result = self.sql_conn.insert(sql)
            return result
        except Exception as e:
            raise e

    def insert_info_redis(self, info, table=''):
        redis_table = settings.REDIS_DETAILLINK_CZOWNER if not table else table
        self.redis_coon.sadd(redis_table, info)